package com.dev.weixin.tools.service.impl;

import java.util.LinkedHashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;

import com.dev.weixin.tools.models.WeixinConfig;
import com.dev.weixin.tools.models.base.AccessToken;
import com.dev.weixin.tools.models.base.IpAddress;
import com.dev.weixin.tools.models.exceptions.ErrorMsgException;
import com.dev.weixin.tools.service.BaseService;
import com.dev.weixin.tools.utils.URLConstants;
import com.dev.weixin.tools.utils.WeixinHttpClient;
import com.dev.weixin.tools.utils.policy.GetRequestPolicy;

/**
 * 基础接口实现
 * @author 飘渺青衣
 * @see
 */
public class BaseServiceImpl implements BaseService {
	
	private final ThreadLocal<WeixinConfig> threadLocal = new ThreadLocal<WeixinConfig>();
	
	private WeixinConfig defaultConfig;
	
	@Autowired
	public BaseServiceImpl(WeixinConfig defaultConfig) {
		this.defaultConfig = defaultConfig;
	}

	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.WeixinToolsService#getAccessToken()
	 */
	@Override
	public String getAccessToken() throws ErrorMsgException {
		WeixinConfig config = this.getWeixinConfig();
		AccessToken accessToken = config.getAccessToken();
		if(accessToken == null || accessToken.isTimeout()) {
			synchronized (config) {
				if(accessToken == null || accessToken.isTimeout()) {
					Map<String, String> params = new LinkedHashMap<String, String>();
					params.put("grant_type", "client_credential");
					params.put("appid", config.getAppId());
					params.put("secret", config.getAppSecret());
					try {
						accessToken = WeixinHttpClient.request(new GetRequestPolicy<AccessToken>(URLConstants.Base.URL_ACCESS_TOKEN, WeixinConfig.ENCODING, params, AccessToken.class));
						config.setAccessToken(accessToken);
						//持久化accessToken
						this.persistWeixinConfig(config);
					} catch (ErrorMsgException e) {
						throw e;
					}
				}
			}
		}
		return accessToken.getAccess_token();
	}

	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.WeixinToolsService#getWeixinConfig()
	 */
	@Override
	public WeixinConfig getWeixinConfig() {
		WeixinConfig config = threadLocal.get();
		return config != null ? config : this.defaultConfig;
	}

	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.WeixinToolsService#getIpAddress()
	 */
	@Override
	public IpAddress getIpAddress() throws ErrorMsgException {
		Map<String, String> params = new LinkedHashMap<String, String>();
		params.put("access_token", this.getAccessToken());
		return WeixinHttpClient.request(new GetRequestPolicy<IpAddress>(URLConstants.Base.URL_IP_LIST, WeixinConfig.ENCODING, params, IpAddress.class));
	}

	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.BaseService#setThreadLocalWeixinConfig(com.dev.weixin.tools.models.WeixinConfig)
	 */
	@Override
	public void setThreadLocalWeixinConfig(WeixinConfig config) {
		this.threadLocal.set(config);
	}

	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.BaseService#removeThreadLocalWeixinConfig()
	 */
	@Override
	public void removeThreadLocalWeixinConfig() {
		this.threadLocal.remove();
	}

	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.BaseService#getWeixinConfig(java.lang.String)
	 */
	@Override
	public WeixinConfig getWeixinConfig(String toUserName) {
		WeixinConfig config = this.threadLocal.get();
		if(config == null) {
			config = this.getPersistWeixinConfig(toUserName);
			this.setThreadLocalWeixinConfig(config);
		}
		return config;
	}
	
	/**
	 * 持久化微信配置，主要是持久化AccessToken，有需要的请重写此方法
	 * @author 飘渺青衣
	 * @version
	 * @param config
	 */
	protected void persistWeixinConfig(WeixinConfig config) {}
	
	/**
	 * 根据toUserName获取微信配置，多微信公众号请重写此方法
	 * @author 飘渺青衣
	 * @version
	 * @param toUserName
	 * @return
	 */
	protected WeixinConfig getPersistWeixinConfig(String toUserName) {
		return this.defaultConfig;
	} 

}
